from driver import RTC
from driver import UART

class SysRtc():
    def __init__(self,port="uart4"):
        self.uart4 = UART()
        self.uart4.open(port)
        self.uart4.on(self._rtc_time)

        self.rtc = RTC()
        self.rtc.open()
        self._last_total_seconds = 0
      

        self.rtc_data = {}   # 通用数据存储
        self.rtc_time = {}
        self.rtc_time_cmd() # 先获取时间


    def rtc_time_cmd(self):
        """
        读取RTC时间
        """
        time_cmd = bytearray([0x68, 0x07, 0x00, 0xFF, 0x11, 0x10, 0x16])
        self.uart4.write(time_cmd)
          

    def rtc_set_time(self,year,month,day,hour,minute,second):
        """
        设置RTC时间
        """
        #帧格式：68 | 长度(低,高) | 模块地址 | 功能码 |     数据域(n字节)  | 校验和 | 16
        #       68  0D 00         FF       10     16 06 12 14 22 24    97    16
        year_2d = year % 100  # 计算年份的两位数表示（0-99）
        # 数据域：年、月、日、时、分、秒
        data_bytes = bytes([year_2d, month, day, hour-8, minute, second])
        # 模块地址和功能码
        module_addr = 0xFF  # 模块地址
        func_code = 0x10    # 设置时间的功能码
        # 计算校验和
        checksum = self._compute_checksum(module_addr, func_code, data_bytes)
      
        frame_len = 13
        len_low = frame_len & 0xFF
        len_high = (frame_len >> 8) & 0xFF

         # 组装完整的命令帧
        time_cmd = bytearray([0x68, len_low,len_high, module_addr, func_code])
        time_cmd.extend(data_bytes)
        time_cmd.append(checksum)
        time_cmd.append(0x16)
        self.uart4.write(time_cmd)

    def _compute_checksum(self, module_addr: int, func_code: int, data_bytes: bytes) -> int:
        """
        校验和：模块地址 + 功能码 + 数据域所有项，每个字节相加，对 256 取余
        """
        return (module_addr + func_code + sum(data_bytes)) & 0xFF

    def _parse_data(self, func_code: int,data_bytes: bytes) -> dict:
        """
        解析数据域8字节:状态、年、月、日、时、分、秒、星期
        """
        if len(data_bytes) < 1:
            raise ValueError("Data field length insufficient")
        
        status = data_bytes[0]
        result = {
            "status": status,
            "success": (status == 0x00),  # 比较状态字节是否为0x00
            "func_code": func_code        # 记录功能码便于识别数据类型
        }

        # 根据功能码解析不同类型的数据
        if func_code == 0x11:  # 时间功能码
            _, yy, mm, dd, hh, minute, ss, weekday = data_bytes[:8]
            result.update({
                "year_2d": yy,             # 两位年份：0-99
                "year": 2000 + yy,         # 便捷字段：按2000年基准换算，按需使用
                "month": mm,
                "day": dd,
                "hour": hh,
                "minute": minute,
                "second": ss,
                "weekday": weekday         # 0-6
            })

        elif func_code == 0x13:  # 示例：其他功能码1
            # 在此添加其他功能码的解析逻辑
            pass
            
        else:  # 未知功能码
            result.update({
                "unknown_func_code": True,
                "raw_data": list(data_bytes)  # 保存原始数据以便后续处理
            })
            
        return result

    def _rtc_time(self,data):
        """
        读取模块时间并解析协议：
        帧格式:68 | 长度(低,高) | 模块地址 | 功能码 |       数据域(n字节)        | 校验和 | 16
        示例： 0x68  0x0F 0x00     0x00    0x11    00 19 09 03 0B 34 10 03    0x88   0x16
        """
        try:
            if not isinstance(data, (bytes, bytearray)):
                print("read_rtc_time: Invalid data type")
                return None
            # 帧头/帧尾检查
            if data[0] != 0x68 or data[-1] != 0x16:
                print("read_rtc_time: Frame header or end error")
                return None
            # 长度字段（总帧长，低字节在前）
            frame_len = data[1] | (data[2] << 8)
            if frame_len != len(data):
                print("read_rtc_time:len={}, act len={}".format(frame_len, len(data)))
                return None

            module_addr = data[3]     # 模块地址
            func_code   = data[4]     # 功能码
            payload     = data[5:-2]   # 数据域
            checksum    = data[-2]    # 校验和

            # 校验和验证
            calc = self._compute_checksum(module_addr, func_code, payload)
            if calc != checksum:
                print("read_rtc_time: Checksum error, Calculate=0x%02X, frame=0x%02X" % (calc, checksum))
                return None

            # 解析数据
            try:
                result = self._parse_data(func_code, payload)
                
                # 根据功能码存储结果并输出信息
                if func_code == 0x11:  # 时间功能码
                    if result["success"]:
                        print("RTC read success: {year}-{month:02d}-{day:02d} {hour:02d}:{minute:02d}:{second:02d} week{weekday}".format(**result))
                        self.rtc.setTime(result["year"],result["month"],result["day"],result["hour"],result["minute"],result["second"])
                        self.rtc_time = result
                    else:
                        print("RTC time status err")

                elif func_code == 0x01:  # 返回功能码
                        print("RTC set time success")
                     
                else:
                    print("Unknown function code: 0x%02X" % func_code)
                    
            except ValueError as ve:
                print("Data parsing error:", ve)
                return None
                
        except Exception as e:
            print("read_rtc_data: Parsing exceptions ->", e)
            return None



    def sys_rtc(self):
        """
        注意:该函数调用的是rtc时间是UTC时间,如果通过sim卡自动校准时间需要加8小时,
              如果是通过外置RTC模块校准时间,则不需要加8小时,因此有sim卡和同时有外置RTC模块时,
              需要注意,可能会被篡改时间,因此,位置模块RTC设置为UTC时间.
        """
        t = self.rtc.getTime()    
        return (t[0], t[1], t[2], t[3]+8, t[4], t[5])

    def set_time(self,year=2024,month=1,day=1,hour=00,minute=00,second=00):

        self.rtc.setTime(year,month,day,hour-8,minute,second)

    def getRtcTime(self):
        mydata = self.sys_rtc()
        # print("mydata:",mydata)
        d="{:04d}-{:02d}-{:02d}".format(mydata[0],mydata[1],mydata[2])
        t="{:02d}:{:02d}:{:02d}".format(mydata[3],mydata[4],mydata[5]) 
        
        datatiemstr = d + ' '+ t
        return datatiemstr

    def get_next_collection_time_with_time(self, interval_seconds):
        """
        根据设定的采集间隔和传入的时间字符串，计算下一个采集时间点
        参数:
        interval_seconds: 采集间隔（秒）
        current_time_str: 当前时间字符串，格式为 "YYYY-MM-DD HH:MM:SS"
        返回: next_time: 下一个采集时间点（秒）
             wait_seconds: 需要等待的秒数
        """
        
        # 支持的固定时间点（秒）
        supported_intervals = [1, 2, 4, 5, 10, 15, 20, 30, 60, 300, 600,
                               900, 1200, 1800, 3600, 5400, 7200, 10800]
        
        # 如果不是预定义的时间点，直接返回间隔时间
        if interval_seconds not in supported_intervals:
            return None, None

        data_t = self.sys_rtc()
        hour, minute, second = data_t[3], data_t[4], data_t[5]
        # 计算当前时间的总秒数（一天内）
        current_total_seconds = hour * 3600 + minute * 60 + second
        # 添加调试信息
        print("Debug - Current time: %02d:%02d:%02d (total: %d seconds)" % 
              (hour, minute, second, current_total_seconds))
        
        # 计算下一个采集时间点
        next_total_seconds = ((current_total_seconds // interval_seconds) + 1) * interval_seconds
      
        # 处理跨越午夜的情况
        if next_total_seconds >= 86400:  # 24 * 3600
            # 检查是否应该在00:00:00采集
            if next_total_seconds == 86400:
                # 正好在午夜采集
                wait_seconds = 86400 - current_total_seconds
                next_total_seconds = 0  # 表示第二天的00:00:00
            else:
                # 跨越到第二天的其他时间点
                next_total_seconds = next_total_seconds - 86400
                wait_seconds = (86400 - current_total_seconds) + next_total_seconds   
        else:
            # 计算需要等待的秒数
            wait_seconds = next_total_seconds - current_total_seconds
        if wait_seconds <= 0:
            wait_seconds = interval_seconds
            
        return next_total_seconds, wait_seconds

        